<template>
	<view class="slider-container" :style="[sliderContainer]">
		<view class="left-bg jp-flex-row jp-main-center jp-cross-center"
			:class="{success:success,error:error}" :style="[leftBg]">
			<slot name="leftBgContent">
				<text v-if="success || error">{{success || error}}</text>
			</slot>
		</view>
		<view v-if="!disable" class="slider-box jp-flex-row jp-main-center jp-cross-center"
			:style="[sliderBox]" @touchmove='onTouchMove' @touchend='onTouchEnd' @mousedown="onMousedown">
			<slot name="sliderBoxContent">
				<!-- <u-icon name="arrow-right-double" :color="activeColor" bold size="44rpx"></u-icon> -->
			</slot>
		</view>
		<view class="right-bg jp-flex-row jp-main-center jp-cross-center" :style="[rightBg]">
			<slot name="rightBgContent">
				<!-- <text v-if="currentValue<((maxValue-minValue)/10.0)">滑动验证</text> -->
			</slot>
		</view>
	</view>
</template>

<script>
	export default {
		name: "jp-slider",
		props: {
			value: { //当前默认值
				type: [String, Number],
				default: 0
			},
			min: { //最小值
				type: [String, Number],
				default: 0
			},
			max: { //最大值
				type: [String, Number],
				default: 100
			},
			disable: {
				type: Boolean,
				default: false
			},
			containerH: { //容器轨道高度 默认px
				type: [String, Number],
				default: 6
			},
			boxW: { //滑块宽度 默认px
				type: [String, Number],
				default: 16
			},
			ignoreBoxW: { //ignoreBoxW=true,滑块能滑到100%；ignoreBoxW=false，滑块不能滑动到100%（滑动拼图，小拼图只能在大图内）
				type: Boolean,
				default: true,
			},
			activeColor: { //滑块左侧轨道背景色
				type: String,
				default: 'var(--uni-color-primary)'
			},
			inactiveColor: { //滑块右侧轨道背景色
				type: String,
				default: '#EBEBEB'
			},
			blockColor: { //滑块背景色
				type: String,
				default: 'var(--uni-color-primary)'
			},
			containerCustomStyle: { //轨道容器样式自定义
				type: Object,
			},
			leftBgCustomStyle: { //滑块左侧轨道样式自定义
				type: Object,
			},
			sliderBoxCustomStyle: { //滑块样式自定义
				type: Object,
			},
			rightBgCustomStyle: { //滑块右侧轨道样式自定义
				type: Object,
			},
		},
		data() {
			return {
				currentValue: 0,
				minValue: 0,
				maxValue: 0,
				mousedown: false,
				success: null,
				error: null,
				canOperation: true, //是否可操作（是否可滑动滑块）

				sliderContainerOffsetX: 0,
				sliderContainerW: 0,
				sliderContainerH: 0,
				sliderContainer: { //容器
					height: 0 + 'px',
				},

				leftBgW: 0,
				leftBg: { //左边背景
					width: 0 + 'px',
				},

				sliderBoxLeft: 0,
				sliderBoxW: 0,
				sliderBox: { //滑块
					left: 0 + 'px',
					width: 0 + 'px',
				},

				rightBgW: 0,
				rightBg: { //右边背景
					width: 0 + 'px',
				},
			};
		},
		created() {
			this.sliderBoxW = this.disable ? 0 : uni.$u.getPx(this.boxW)
			this.sliderBox.width = this.sliderBoxW + 'px'
			this.sliderContainerH = uni.$u.getPx(this.containerH)
			this.sliderContainer.height = this.sliderContainerH + 'px'
			this.init()
		},
		watch: {
			value(e) {
				this.init()
			},
			boxW(e) {
				this.sliderBoxW = this.disable ? 0 : uni.$u.getPx(this.boxW)
				this.sliderBox.width = this.sliderBoxW + 'px'
			}
		},
		mounted() {
			// #ifdef H5
			window.removeEventListener('mouseup', this.onMouseup)
			window.removeEventListener('mousemove', this.onTouchMove)
			window.addEventListener('mouseup', this.onMouseup)
			window.addEventListener('mousemove', this.onTouchMove)
			// #endif
		},
		beforeDestroy() {
			// #ifdef H5
			window.removeEventListener('mouseup', this.onMouseup)
			window.removeEventListener('mousemove', this.onTouchMove)
			// #endif
		},
		methods: {
			init() {
				this.currentValue = this.value
				this.minValue = this.min
				this.maxValue = this.max
				if (this.minValue > this.maxValue) {
					this.minValue = this.maxValue
				}
				if (this.currentValue < this.minValue) {
					this.currentValue = this.minValue
				}
				if (this.currentValue > this.maxValue) {
					this.currentValue = this.maxValue
				}

				this.leftBg.backgroundColor = this.activeColor
				this.rightBg.backgroundColor = this.inactiveColor
				this.sliderBox.backgroundColor = this.blockColor

				this.$nextTick(() => {
					if (this.containerCustomStyle) {
						this.sliderContainer = uni.$u.deepMerge(this.sliderContainer, this.containerCustomStyle)
					}
					if (this.leftBgCustomStyle) {
						this.leftBg = uni.$u.deepMerge(this.leftBg, this.leftBgCustomStyle)
					}
					if (this.sliderBoxCustomStyle) {
						this.sliderBox = uni.$u.deepMerge(this.sliderBox, this.sliderBoxCustomStyle)
					}
					if (this.rightBgCustomStyle) {
						this.rightBg = uni.$u.deepMerge(this.rightBg, this.rightBgCustomStyle)
					}
				})

				//slider拖动的范围是 sliderContainerW-sliderBoxW(如果sliderBoxW足够小可以忽略不计)
				//延迟0.3秒重新渲染sliderContainerW拿到的值才没有误差
				setTimeout(() => {
					this.$nextTick(() => {
						let query = uni.createSelectorQuery().in(this);
						query.select('.slider-container').boundingClientRect();
						query.exec(res => {
							this.sliderContainerOffsetX = res[0].left
							this.sliderContainerW = res[0].width
							let clientX = ((this.currentValue - this.minValue) / (this.maxValue -
									this
									.minValue)) * (this
									.sliderContainerW - (this.ignoreBoxW ? this.sliderBoxW : 0)) +
								this.sliderContainerOffsetX
							this.valueHandle(clientX)
						});
					})
				}, 300)

			},
			onTouchMove(e) {
				if (this.canOperation == false) {
					return
				}
				if (this.mousedown == true) {
					if (e.type == 'mousemove') {
						this.valueHandle(e.clientX)
					} else {
						if (e.changedTouches) {
							let clientX = e.changedTouches[0].clientX
							this.valueHandle(clientX)
						}
					}
				} else {
					if (e.changedTouches) {
						let clientX = e.changedTouches[0].clientX
						this.valueHandle(clientX)
					}
				}

			},
			onTouchEnd() {
				if (this.canOperation == false) {
					return
				}
				console.log('【jp-slider onTouchEnd】currentValue=>' + this.currentValue)
				this.mousedown = 0
				this.$emit('change', this.currentValue)
			},
			onMousedown() {
				if (this.canOperation == false) {
					return
				}
				this.mousedown = true
			},
			onMouseup() {
				if (this.canOperation == false) {
					return
				}
				if (this.mousedown == true) {
					this.mousedown = false
					this.onTouchEnd()
				}
			},
			resultHandle(success, error) {
				this.canOperation = false
				this.success = success
				this.error = error
				return new Promise((resolve, reject) => {
					setTimeout(() => {
						this.resetState()
						resolve()
					}, 700)
				})
			},
			resetState() {
				this.success = null
				this.error = null
				this.canOperation = true
				this.init()
			},
			valueHandle(clientX) {
				// clientX是相对于屏幕的(原点在屏幕的左上角)，要求出相对于父组件的需要减去父组件的clientX
				let sliderBoxOffsetX = clientX - this.sliderContainerOffsetX

				if (sliderBoxOffsetX < 0) {
					sliderBoxOffsetX = 0
				} else if (sliderBoxOffsetX > (this.sliderContainerW - this.sliderBoxW)) {
					sliderBoxOffsetX = this.sliderContainerW - this.sliderBoxW
				}

				this.leftBgW = sliderBoxOffsetX + this.sliderBoxW / 2.0
				this.leftBg.width = this.leftBgW + 'px'
				this.sliderBoxLeft = sliderBoxOffsetX
				this.sliderBox.left = this.sliderBoxLeft + 'px'

				this.rightBgW = this.sliderContainerW - this.leftBgW
				this.rightBg.width = this.rightBgW + 'px'

				this.currentValue = ((sliderBoxOffsetX) / (this.sliderContainerW - (this.ignoreBoxW ? this.sliderBoxW :
					0))) * (this
					.maxValue - this.minValue) + this.minValue
				if (this.currentValue > this.minValue && this.currentValue < this.maxValue) {
					this.leftBg['border-radius'] = '8rpx 0 0 8rpx'
					this.rightBg['border-radius'] = '0 8rpx 8rpx 0'
				} else {
					this.leftBg['border-radius'] = '8rpx'
					this.rightBg['border-radius'] = '8rpx'
				}

				this.$emit('changing', sliderBoxOffsetX, this.currentValue)
				console.log('【jp-slider valueHandle】currentValue=>' + this.currentValue + ';sliderBoxOffsetX=>' +
					sliderBoxOffsetX)
			}
		}
	}
</script>

<style lang="scss" scoped>
	.slider-container {
		position: relative;
		background-color: transparent;
		border-radius: 8rpx;

		.success {
			background-color: $uni-color-success !important;
		}

		.error {
			background-color: $uni-color-error !important;
		}

		.left-bg {
			position: absolute;
			top: 0;
			bottom: 0;
			left: 0;
			border-radius: 8rpx;
			font-size: 28rpx;
			overflow: hidden;
			color: white;
			z-index: 2;
		}

		.slider-box {
			position: absolute;
			top: -10rpx;
			bottom: -10rpx;
			left: 0;
			border-radius: 50%;
			box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.3);
			z-index: 3;
		}

		.right-bg {
			position: absolute;
			top: 0;
			bottom: 0;
			right: 0;
			border-radius: 8rpx;
			font-size: 28rpx;
			overflow: hidden;
			color: $text-auxiliary;
			z-index: 1;
		}
	}
</style>